package com.dove.websocket;

import com.dove.config.WebSocketConfig;
import com.dove.constant.Constants;
import com.dove.domain.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @ProjectName: websocket
 * @Package: com.dove.websocket
 * @ClassName: WebSocketServer
 * @Description: websocket连接、接收及发送的具体实现类
 * @Author: dove
 * @CreateDate: 2018/7/22 10:13
 * @Version: 1.0
 * <p>Copyright: Copyright (c) 2018</p>
 */
@ServerEndpoint(value = "/websocket", configurator = WebSocketConfig.class)
@Component
public class WebSocketServer {
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    //保存某个客户端的session信息 需要通过它来给特定客户端发送数据
    private HttpSession httpSession;
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        log.info("session:{}", config.getUserProperties().get(HttpSession.class.getName()));
        HttpSession httpSession = (HttpSession)config.getUserProperties().get(HttpSession.class.getName());
        User user = (User)httpSession.getAttribute(Constants.USER);
        if(user != null){
            this.session = session;
            this.httpSession = httpSession;
            webSocketSet.add(this);     //加入set中
            log.info("有新连接加入！当前在线人数为" + webSocketSet.size());
            try {
                sendMessage("有新连接加入！当前在线人数为" + webSocketSet.size());
            } catch (IOException e) {
                log.error("websocket IO异常",e);
            }
        }else{
            //用户未登陆
            try {
                session.close();
            } catch (IOException e) {
                log.error("websocket--用户未登陆 session.close异常：",e);
            }
        }

    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        log.info("有一连接关闭！当前在线人数为" + webSocketSet.size());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("来自客户端的消息:" + message);

        //群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                log.error("websocket 群发消息失败：",e);
            }
        }
    }

     /**
      * 群发自定义消息
      * */
    public static void sendInfo(String message) throws IOException {
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                log.error("websocket 群发自定义消息失败：",e);
                continue;
            }
        }
    }

    /**
     * 指定发送某一用户
     * */
    public static void sendInfoToUser(String message,HttpSession session1) throws IOException {
        for (WebSocketServer item : webSocketSet) {
            try {
                if (item.httpSession.getId().equals(session1.getId())) {
                    log.info("给特定用户发送消息,用户sessionID{}，发送内容{}",session1.getId(),message);
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                log.error("websocket 指定发送某一用户消息失败：",e);
            }
        }
    }

    /**
     * 发生错误时候发送
     * */
    @OnError
    public void onError(Session session, Throwable e) {
        webSocketSet.remove(this);
        log.info("【websocket消息】连接出错或未关闭socket：" ,e);

    }

    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }



}
